package org.funsciencewithyourcomputer.client;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import com.google.gwt.user.client.Cookies;

/**
 * Cookie is used to save high scores. Format: version1: High
 * Score,name1,score1,name2,score2,..: Other Category,name1,score1,..
 * 
 * Format version2: name1,language,number stegs,best score,best word,number
 * plays, cumulative score
 */
public class HighScore {

	// Persisted in cookie
	String name;
	String language;
	int countStegs;
	int bestScore;
	String bestWord;
	int numberPlays;
	int cumulativeScore;
	boolean lastPlayer;

	static final String COOKIE_HIGH_SCORE = "HIGH_SCORE";

	// We remember at most 10 players
	static final int MAX_PLAYERS = 10;

	static List<HighScore> scores = new ArrayList<HighScore>();

	static final String SIGNATURE = "STEG03";

	public static void readCookie() {
		scores.clear();
		String cookie = Cookies.getCookie(COOKIE_HIGH_SCORE);
		if (cookie == null || !cookie.startsWith(SIGNATURE))
			return;
		String[] players = cookie.substring(SIGNATURE.length()).split(":");
		for (String player : players) {
			try {
				String[] data = player.split(",");
				HighScore hs = new HighScore();
				hs.name = data[0];
				hs.language = data[1];
				hs.countStegs = Integer.parseInt(data[2]);
				hs.bestScore = Integer.parseInt(data[3]);
				hs.bestWord = data[4];
				hs.numberPlays = Integer.parseInt(data[5]);
				hs.cumulativeScore = Integer.parseInt(data[6]);
				hs.lastPlayer = Boolean.parseBoolean(data[7]);
				scores.add(hs);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		// sort by count stegs (primary), best score (secondary)
		Collections.sort(scores, new Comparator<HighScore>() {

			public int compare(HighScore o1, HighScore o2) {
				if (o1.countStegs > o2.countStegs)
					return -1;
				if (o1.countStegs < o2.countStegs)
					return 1;
				return o2.bestScore - o1.bestScore;
			}
		});
	}

	static HighScore getHighScore(String name, String language) {
		for (HighScore score : scores) {
			if (score.name.equals(name) && score.language.equals(language))
				return score;
		}
		return null;
	}

	/**
	 * Update given
	 * 
	 * @param ranking
	 * @param newScore
	 * @return
	 */
	public static boolean saveCookie(Score score) {
		readCookie();
		HighScore hs = getHighScore(score.name, score.language);
		if (hs == null) {
			hs = new HighScore();
			hs.name = score.name;
			hs.language = score.language;
			hs.bestWord = "";
			scores.add(hs);
		}
		if (score.getCountLetters() == 0)
			hs.countStegs++;
		if (score.score > hs.bestScore)
			hs.bestScore = score.score;
		hs.cumulativeScore += score.score;
		int bestWordScore = score.getWordScore(hs.bestWord);
		String newBestWord = score.bestWord;
		int newBestWordScore = score.bestWordScore;
		if (newBestWordScore > bestWordScore)
			hs.bestWord = newBestWord;
		hs.numberPlays++;
		hs.lastPlayer = true;
		// sort by count stegs (primary), best score (secondary)
		Collections.sort(scores, new Comparator<HighScore>() {

			public int compare(HighScore o1, HighScore o2) {
				if (o1.countStegs > o2.countStegs)
					return -1;
				if (o1.countStegs < o2.countStegs)
					return 1;
				return o2.bestScore - o1.bestScore;
			}
		});
		String result = "";
		String sep = ",";
		// todo verify we store at most 10 french and 10 english
		for (HighScore s : scores) {
			result += s.name + sep + s.language + sep + s.countStegs + sep
					+ s.bestScore + sep + s.bestWord + sep
					+ s.numberPlays + sep + s.cumulativeScore + sep + (s == hs ? "true" : "false") + ":";
		}
		Date oneYear = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60
				* 1000);
		Cookies.setCookie(COOKIE_HIGH_SCORE, SIGNATURE + result, oneYear);
		// lazy way to resort the results
		readCookie();
		return true;
	}

	public static String getLastPlayer() {
		for (HighScore hs : scores) {
			if (hs.lastPlayer)
				return hs.name;
		}
		return NLS.get(NLS.DEFAULT_PLAYER_NAME);
	}
	
	public static Collection<String> getNames() {
		List<String> result = new ArrayList<String>();
		String language = NLS.getLanguage();
		for (HighScore hs : scores) {
			if (hs.language.equals(language))
				result.add(hs.name);
		}
		return result;
	}
}
